package com.onadake.dao;

import java.util.List;
import java.util.Map;
import java.util.Set;

import com.onadake.domain.Data;
import com.onadake.domain.DataFilterColumns;
import com.onadake.domain.Entity;
import com.onadake.domain.Relation;
import com.onadake.domain.RelationFilterColumns;
import com.onadake.domain.RelationType;
import com.onadake.domain.query.Criterium;
import com.onadake.domain.query.Filter;

/**
 * Defines data access layer for manipulation with entities.
 * <p></p>
 * Standard column format is 'source-column' where:
 * <ul>
 *   <li> source can be core or join </li>
 *   <li> If source is core, then column is column name in the core table </li>
 *   <li> If source is join, then column is table_name.column_name </li>
 * </ul>
 * 
 * @author radek.hecl
 *
 */
public interface EntityDao {

    /**
     * Inserts the specified entity.
     * 
     * @param entity entity to be inserted
     */
    public void insertEntity(Entity entity);
    
    /**
     * Deletes the specified entity.
     * 
     * @param code entity codes
     */
    public void deleteEntity(String code);
    
    /**
     * Selects all entities which satisfies the specified criteria
     * 
     * @param joinsData data from other tables which will be returned in the joins property.
     *     Format is table_name.column_name
     * @param filter filter object with column in the entity format
     * @return entities which match the filter
     */
    public List<Entity> selectEntities(Set<String> joinsData, Filter<String> filter);
    
    /**
     * Counts all entities which satisfies the specified criteria.
     * 
     * @param criteria criteria with column in the entity format
     * @return how many entities satisfies the criteria
     */
    public long countEntities(Set<Criterium<String>> criteria);
    
    /**
     * Updates entity name.
     * 
     * @param code code of the entity
     * @param name new name of the entity
     */
    public void updateEntityName(String code, String name);
    
    /**
     * Replaces entity profile.
     * This means all the old profile values are deleted and new ones are inserted.
     * 
     * @param code entity code
     * @param profile new profile
     */
    public void replaceEntityProfile(String code, Map<String, String> profile);
    
    /**
     * Updates the specified entity join.
     * 
     * @param code entity code
     * @param join identification of the join, format is table_name.column_name
     * @param value new value which will be used
     */
    public void updateEntityJoin(String code, String join, Object value);
  
    /**
     * Inserts new relation.
     * 
     * @param subjectCode subject entity code
     * @param objectCode object entity code
     * @param type type of the relation
     */
    public void insertRelation(String subjectCode, String objectCode, RelationType type);
    
    /**
     * Deletes relation.
     * 
     * @param subjectCode subject entity code
     * @param objectCode object entity code
     * @param type type of the relation
     */
    public void deleteRelation(String subjectCode, String objectCode, RelationType type); 

    /**
     * Selects all relations according filter.
     * 
     * @param filter filter object
     * @return relations which matches the filter
     */
    public List<Relation> selectRelations(Filter<RelationFilterColumns> filter);
    
    /**
     * Counts how many relations satisfies the criteria.
     * 
     * @param criteria criteria to be satisfied
     * @return how many relations satisfies the criteria
     */
    public long countRelations(Set<Criterium<RelationFilterColumns>> criteria);
    
    /**
     * Inserts data block
     * 
     * @param data data object which will be inserted
     * @param blob data blob
     */
    public void insertData(Data data, byte[] blob);
    
    /**
     * Deletes data block for the specified entity.
     * 
     * @param data data object to be deleted
     */
    public void deleteData(Data data);
    
    /**
     * Selects all data blocks according filter.
     * 
     * @param filter filter object
     * @return data blocks which matches the filter
     */
    public List<Data> selectDatas(Filter<DataFilterColumns> filter);
    
    /**
     * Counts how many data blocks satisfies the criteria.
     * 
     * @param criteria criteria to be satisfied
     * @return how many data blocks satisfies the criteria
     */
    public long countDatas(Set<Criterium<DataFilterColumns>> criteria);

    /**
     * Selects data blob for the particular data object.
     * 
     * @param data data object to be used
     * @return data blob
     */
    public byte[] selectDataBlob(Data data);
}
